﻿using Core.App.Attributes;
using Microsoft.Extensions.DependencyModel;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Runtime.Loader;
using System.Text;
using System.Threading.Tasks;

namespace Core.App
{
    public static class App
    {
        static App()
        {
            ProjectDlls = GetProjectDlls();
            EffectiveType = GetProjectTypes();
        }
        /// <summary>
        /// 所有项目程序集
        /// </summary>
        private static IEnumerable<Assembly> ProjectDlls;
        /// <summary>
        /// 程序集内全部有效的类型
        /// </summary>
        private static List<Type> EffectiveType;
        /// <summary>
        /// 获取所有程序集
        /// </summary>
        /// <returns></returns>
        public static IEnumerable<Assembly> GetDlls() => ProjectDlls;
        /// <summary>
        /// 获取程序内有效type
        /// </summary>
        /// <returns></returns>
        public static List<Type> GetTypes() => EffectiveType;

        private static List<Type> GetProjectTypes()
        {
            List<Type> EffectiveType = new List<Type>();
            foreach (var dll in ProjectDlls)
            {
                var dllType=dll.GetTypes().AsEnumerable().Where(t => t.IsPublic&&t.GetCustomAttribute(typeof(SkipScanAttribute))==null).ToList();
                EffectiveType.AddRange(dllType);
            }
            return EffectiveType;
        }
        /// <summary>
        /// 私有方法 获取程序内所有的dll
        /// </summary>
        /// <returns></returns>
        private static IEnumerable<Assembly> GetProjectDlls()
        {
            var scanAssemblies = DependencyContext.Default.CompileLibraries
               .Where(u => (u.Type == "project" && !(u.Type == "package"  && u.Type == "reference")))
               .Select(u => AssemblyLoadContext.Default.LoadFromAssemblyName(new AssemblyName(u.Name)));
            return scanAssemblies;
        }
        /// <summary>
        /// 获取请求生命周期的服务
        /// </summary>
        /// <typeparam name="TService"></typeparam>
        /// <param name="serviceProvider"></param>
        /// <returns></returns>
        public static TService GetService<TService>(Type type)
            where TService : class
        {
            return HttpHelper.HttpContextHelper.GetCurrentHttpContext().RequestServices.GetService(type) as TService;
        }

    }
}
